package com.ymx.darling.mapper;

import com.ymx.darling.cursor.Cursor;
import com.ymx.darling.dialect.page.Page;
import com.ymx.darling.wrapper.QueryWrapper;
import com.ymx.darling.wrapper.UpdateWrapper;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * 该接口由其他Mapper继承此接口实现实体类的增删改查
 * @author 爱Java的小于
 * @param <T> 实体类型
 */
public interface EntityMapper <T>{
    /**
     * 根据wrapper查询一个实体
     * @param wrapper 条件构造器
     * @return T
     */
    T selectOne(QueryWrapper wrapper);

    /**
     * 根据wrapper返回一个实体 并指定映射实体类型
     * @param wrapper 条件构造器
     * @param eClass 指定映射类型
     * @return E
     * @param <E> E
     */
    <E> E selectOneAs(QueryWrapper wrapper, Class<?> eClass);

    /**
     * 根据id查询一个实体
     * @param id id值
     * @return T
     */
    default T selectById(Serializable id) {
        return null;
    }

    /**
     * 批量id查询多个实体
     * @param idList 保存多个id的List
     * @return list
     */
    List<T> selectBatchIds(List<? extends Serializable> idList);

    /**
     * 根据wrapper返回多个实体
     * @param wrapper 条件构造器
     * @return list
     */
    List<T> selectList(QueryWrapper wrapper);

    /**
     * 根据wrapper返回多个实体 并指定映射实体类型
     * @param wrapper 条件构造器
     * @param type 指定实体类型
     * @return list 没有记录返回空集合
     * @param <E> E
     */
    <E> List<E> selectListAs(QueryWrapper wrapper, Class<?> type);



    /**
     * 查询所有数据
     * @return list
     */
    default List<T> selectAll() {
        return this.selectList(null);
    }


    /**
     * 根据wrapper返回多个实体 并将实体放入Map集合中
     * @param wrapper 条件构造器
     * @param key 指定实体的那个字段作为map的key
     * @return map 没有记录返回空Map
     * @param <K> K 实体的字段类型
     */
    <K> Map<K, T> selectMap(QueryWrapper wrapper, String key);

    /**
     * 根据wrapper返回多个map 并将map放入Map集合中
     * @param wrapper 条件构造器
     * @param key 指定表的哪个字段作为key
     * @return map 没有记录返回空Map
     * @param <K> K 表的字段类型
     */
    <K, E> Map<K, E> selectMapAs(QueryWrapper wrapper, Class<?> asType, String key);

    /**
     * 根据wrapper返回一个分页实体
     * 调用此方法前必须手动设置QuerySetting.setPage定义分页参数
     * @param wrapper 条件构造器
     * @return page
     */
    Page<T> selectPage(QueryWrapper wrapper);

    /**
     * 根据wrapper返回条件的总记录数
     * @param wrapper 条件构造器
     * @return int
     */
    Integer selectCount(QueryWrapper wrapper);

    /**
     * 统计表行数 默认根据id字段统计 id不存在使用'*'
     * @return int
     */
    default Integer selectCount() {
        return this.selectCount(null);
    }

    /**
     * 根据wrapper返回一个游标实体
     * @param wrapper 条件构造器
     * @param fetchSize 每次重数据库读取的数据条数
     * @return cursor
     */
    Cursor<T> selectCursor(QueryWrapper wrapper, int fetchSize);

    /**
     * 根据wrapper返回一个游标实体并映射指定类型
     * @param wrapper 条件构造器
     * @param type 映射类型
     * @param fetchSize 每次重数据库读取的数据条数
     * @return cursor
     * @param <E> E
     */
    <E> Cursor<E> selectCursor(QueryWrapper wrapper, Class<?> type, int fetchSize);

    /**
     * 插入一个实体
     * @param entity entity
     * @return int
     */
    Integer insert(T entity);

    /**
     * 插入多个实体
     * @param entityList 多个实体放入list
     * @return int
     */
    Integer insertBatch(List<T> entityList);

    /**
     * 分批插入多个实体
     * @param entityList 多个实体放入list
     * @param batchSize 指定批次
     * @return int
     */
    Integer insertBatch(List<T> entityList, int batchSize);

    /**
     * 根据id删除一条数据
     * @param id id值
     * @return int
     */
    Integer deleteById(Serializable id);

    /**
     * 根据多个id删除多个数据
     * @param ids 多个id放入list
     * @return int
     */
    Integer deleteBatchIds(List<? extends Serializable> ids);

    /**
     * 根据wrapper删除数据
     * @param wrapper 条件构造器
     * @return int
     */
    Integer delete(UpdateWrapper wrapper);

    /**
     * 根据wrapper更新数据
     * @param wrapper 条件构造器
     * @return int
     */
    Integer update(UpdateWrapper wrapper);

    /**
     * 以实体中id值为条件更新记录 不会更新属性为null的字段
     * @param entity 实体
     * @return int
     *
     */
    Integer update(T entity);

    /**
     * 以实体种中id值为条件更新记录 更新所有属性
     * @param entity 实体
     * @return int
     */
    Integer updateAll(T entity);
}
